#include "outils.h"
#include "Vue.h"
#include "Scene.h"
#include "Rattaupes.h"
#include "meoliste.h"
#include "RegleDuJeu.h"
#include "Combat.h"
#include "Race.h"

/* Déclaration des prototypes pour les mettre dans l'ordre souhaité */
int main(void);
void* Jeu_deroulement(void *vJeufin);
void Jouer (SDL_Surface* ecran, int32_t eNumJoueur, SOCKET csock, int32_t* eJeufin, int32_t eChargement);
void* Jeu_Termine (void* vJeufin);
SOCKET Connection_serveur(int ePort);
void Menu_Quitter(int32_t* eJeufin, SOCKET csock);
te_Race ChoisirRace(SDL_Surface* ecran, int32_t* eJeufin, t_motte** pMotte, t_liste* pRattaupe, SOCKET csock);

int main(void){
	/* La fonction main créer 2 processus, un pour le déroulement du jeu (principale), l'autre pour la fin du jeu */
	int32_t* eJeufin=(int32_t*)malloc(sizeof(int32_t));
	pthread_t thread_principal,thread_secondaire;
	
	*eJeufin=0;

	Alea0(); /* S'occupe de rendre le jeu aléatoire avec srand */

	pthread_create(&thread_principal, NULL, Jeu_Termine, eJeufin);
	pthread_create(&thread_secondaire, NULL, Jeu_deroulement, eJeufin);	
		
	pthread_join(thread_principal, NULL);
	pthread_join(thread_secondaire, NULL);

	return EXIT_SUCCESS;

}

void* Jeu_deroulement(void *vJeufin){
	/* Thread principale s'occupant du menu et de la connection au serveur sur le 1er port */
	int32_t eNumJoueur;
	int32_t eChargement;
	int32_t* eJeufin=vJeufin;
	int continuer = 1;
	SOCKET csock;

	SDL_Surface *ecran = NULL, *menu = NULL, *icone = NULL;
	SDL_Rect positionMenu;
	SDL_Event event;

	SDL_Init(SDL_INIT_VIDEO);

	/* Configuration de l'icône du jeu */
	icone = IMG_Load("./images/icone.bmp");
	SDL_SetColorKey(icone, SDL_SRCCOLORKEY, SDL_MapRGB(icone->format, 62, 142, 171));
	SDL_WM_SetIcon(icone, NULL);
	SDL_FreeSurface(icone);

	ecran = SDL_SetVideoMode(LARGEUR_FENETRE, HAUTEUR_FENETRE+ESPACE_MENU, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);

	/* Configuration du titre */
	SDL_WM_SetCaption("Koh-Lantaupe", NULL);

	menu = IMG_Load("./images/menu.jpg");
	positionMenu.x = 0;
	positionMenu.y = 0;

	/* Se connecte au serveur sur le 1er port et reçois son numéro de joueur */
	csock = Connection_serveur(11123);
	if(csock==-1){
		menu = IMG_Load("./images/co_client_fail.jpg");
		SDL_BlitSurface(menu, NULL, ecran, &positionMenu);
		SDL_Flip(ecran);
		sleep(3);
		SDL_FreeSurface(menu);
		Menu_Quitter(eJeufin, csock);
	}

	recv(csock, (char *)&eNumJoueur, sizeof(eNumJoueur), 0);
	recv(csock, (char *)&eChargement, sizeof(eChargement), 0);
	eNumJoueur = ntohl(eNumJoueur);
	eChargement = ntohl(eChargement);

	SDL_BlitSurface(menu, NULL, ecran, &positionMenu);
	SDL_Flip(ecran);

	/* Menu de début du jeu */
	while (continuer)
	{
		SDL_WaitEvent(&event);
		switch(event.type)
		{
			case SDL_QUIT:
				SDL_FreeSurface(menu);
				Menu_Quitter(eJeufin, csock);
				break;
			case SDL_KEYDOWN:
				switch(event.key.keysym.sym)
				{
					case SDLK_ESCAPE: /* Veut arrêter le jeu */
						SDL_FreeSurface(menu);
						Menu_Quitter(eJeufin, csock);
					   	break;
					case SDLK_F1: /* Demande à jouer */
						SDL_FreeSurface(menu);
					    	Jouer(ecran,eNumJoueur,csock,eJeufin,eChargement);
						continuer=0;
					    	break;
					case SDLK_F2: 
						init_RegleDuJeu(ecran);
						SDL_BlitSurface(menu, NULL, ecran, &positionMenu);
						SDL_Flip(ecran);
						break;
					default:
						break;
				}
			 break;
		}

	}

	return vJeufin;
}

void Jouer (SDL_Surface* ecran, int32_t eNumJoueur, SOCKET csock, int32_t* eJeufin, int32_t eChargement){
	/* Fonction s'occupant de tout ce qui se déroule à chaque tour du jeu */

	int32_t eTour=0, eNombreJoueurPosition, pret=htonl(1);
	char sTour[50], sNumJoueur[100];
	int32_t  eContinueJeu;
	t_motte** pMotte= Vue_init();
	t_liste* pRattaupe = Rattaupes_init();
	te_Race Race;
	SDL_Surface *SDL_Texte = NULL, *SDL_Clean = NULL;
	
	if(eChargement==0){
		Race=ChoisirRace(ecran,eJeufin,pMotte,pRattaupe,csock);
	}

	SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
	SDL_Flip(ecran);

	send(csock, (char const*)&pret, sizeof(pret), 0); /* Envoie au serveur le signal disant que le client est prêt à jouer */

	while(*eJeufin==0){ /* Tant que eJeufin ne change pas sur le 2ème port signalant la fin du jeu */
		recv(csock, (char *)&eContinueJeu, sizeof(eContinueJeu), 0);
		eContinueJeu=ntohl(eContinueJeu);
		if(eContinueJeu==0)
			continue;
		usleep(50);
		Recevoir_combat(ecran,csock,pMotte);
		usleep(50);
		Recevoir_mort(pMotte,ecran,csock);
		usleep(50);
		Recevoir_Reproduction(pMotte,ecran,csock);
		usleep(50);
		Recevoir_Accouchement(pMotte,ecran,csock);
		eNombreJoueurPosition= Recevoir_pMotte(pMotte,&eTour,csock);
		Vue_afficher(pMotte,ecran);
		SDL_Rect_Blanc(ecran,SDL_Clean, ESPACE_MENU, LARGEUR_FENETRE, 0, HAUTEUR_FENETRE); /* Nettoie la zone de menu */
		sprintf(sTour, "Tour n°%i de Koh-Lantaupe !",eTour+1);
		SDL_Ecrire(ecran, SDL_Texte, sTour, 5, HAUTEUR_FENETRE+5);
		SDL_Flip(ecran);
		if (eNombreJoueurPosition==eNumJoueur){
			Recevoir_pRattaupe(pRattaupe, csock);
			usleep(100);
			if(eChargement==0&&eTour==0){
				InitialisationRace(Race,pRattaupe);
			}
			sprintf(sNumJoueur, "Joueur de l'équipe n°%i, à vous de jouer !",eNumJoueur);
			SDL_Ecrire(ecran, SDL_Texte, sNumJoueur, 5, HAUTEUR_FENETRE+20);
			SDL_Flip(ecran);
			Scene_Tour_Suivant(pRattaupe,pMotte,ecran,eJeufin,csock);
			Envoyer_pMotte(pMotte, csock);
			Envoyer_pRattaupe(pRattaupe, csock);
		}
	}

	/* Si le jeu s'est terminé jusqu'au bout on affiche le palmarès */
	if(*eJeufin==1){
		Vue_PalmaresAfficher(ecran);
		sleep(3);
	}


	/* On vide les allocations dynamiques */
	SDL_FreeSurface(SDL_Texte);
	SDL_FreeSurface(SDL_Clean);
	Quitter(eJeufin,pMotte,pRattaupe,csock);
}

void* Jeu_Termine (void* vJeufin){
	/* Fonction se connectant au serveur sur un autre port et attendant le signal de fin du jeu pour transmettre au thread principale */
	SOCKET csockfin;

	int32_t* eJeufin=vJeufin;
 
	csockfin = Connection_serveur(11134);
	recv(csockfin, (char*)eJeufin, sizeof(eJeufin), 0);
	*eJeufin=ntohl(*eJeufin);

	/* Permet l'écriture du palmarès dans un fichier */
	if(*eJeufin==1)
		Vue_Palmares(csockfin);
	
	shutdown(csockfin, 2);
	close(csockfin);

	return vJeufin;

}

SOCKET Connection_serveur(int ePort){
	/* Permet la connection à un serveur avec le port en paramètre, lit l'ip contenu dans le fichier config.txt  */
	
	#if defined (WIN32)
		WSADATA WSAData;
		int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
	#else
		int erreur = 0;
	#endif


	SOCKET csock;
	SOCKADDR_IN sin;

	/* L'ip du serveur se trouver dans le fichier config.txt */
	FILE* config;
	char sIpConfig[15];
	struct timeval tv;
	fd_set fdset;

	config = fopen("config.txt", "r"); /* Créer le fichier en permission lecture */

	if (config != NULL){
		while(!feof(config)){
			fscanf(config, "%s", sIpConfig);
		}
	}

	fclose(config);

	/* Si les sockets Windows fonctionnent */
	if(!erreur)
	{
		/* Création de la socket */
		csock = socket(AF_INET, SOCK_STREAM, 0);
		/*#if defined (WIN32) || defined (_WIN32)
			ioctlsocket (csock, FIONBIO, &arg);
		#elif defined (__linux) || defined (linux)
			fcntl(csock, F_SETFL, O_NONBLOCK);
		#endif*/

		/* Configuration de la connexion */
		sin.sin_addr.s_addr = inet_addr(sIpConfig);
		sin.sin_family = AF_INET;
		sin.sin_port = htons(ePort);

		/* Si l'on a réussi à se connecter */
		if(connect(csock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
		{
			FD_ZERO(&fdset);
			FD_SET(csock, &fdset);
			tv.tv_sec = 10;             /* 10 second timeout */
			
			if (select(csock + 1, NULL, &fdset, NULL, &tv) == 1)
			{
				int so_error;
				socklen_t len = sizeof so_error;

				getsockopt(csock, SOL_SOCKET, SO_ERROR, &so_error, &len);

			}
		}
		else {
			return -1;
		}

	}

	return csock;

}

void Menu_Quitter(int32_t* eJeufin, SOCKET csock){
	/* S'occupe de quitter le jeu lorsqu'il est encore au menu */
	free(eJeufin);
	shutdown(csock, 2);
	close(csock);
	SDL_Quit();
	exit(EXIT_SUCCESS);
}

te_Race ChoisirRace(SDL_Surface* ecran, int32_t* eJeufin, t_motte** pMotte, t_liste* pRattaupe, SOCKET csock){
	/* Fonction permettant au joueur de choisir sa race si le jeu n'a pas été chargé */
	SDL_Surface *menu = NULL;
	SDL_Event event;
	SDL_Rect positionMenu;
	int continuer = 1;

	menu = IMG_Load("./images/Race.jpg");
	positionMenu.x = 0;
	positionMenu.y = 0;

	SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 161, 161, 160));
	SDL_BlitSurface(menu, NULL, ecran, &positionMenu);
	SDL_Flip(ecran);
	

	while (continuer)
	{
		SDL_WaitEvent(&event);
		switch(event.type)
		{
			case SDL_QUIT:
				SDL_FreeSurface(menu);
				Quitter(eJeufin,pMotte,pRattaupe,csock);
				break;
			case SDL_KEYDOWN:
				switch(event.key.keysym.sym)
				{
				case SDLK_ESCAPE:
					break;
				case SDLK_F1:
					SDL_FreeSurface(menu);
					return Reproducteur;
					break;
				case SDLK_F2:
					SDL_FreeSurface(menu);
					return Guerrier;
					break;
				case SDLK_F3:
					SDL_FreeSurface(menu);
					return Defenseur;
					break;
				case SDLK_F4:
					SDL_FreeSurface(menu);
					return Cuisinier;
					break;
				default:
					break;
				}
			   break;
		}
	}
	return Novice;
}
